using System;
using UnityEngine;

public class MagnusForceAndAirResistanceSquaredBallFlight : BallFlight
{
	public static class PhysicsHelperFunctions
	{
		private static float SilhouetteArea(float radius)
		{
			return (float)Math.PI * radius * radius;
		}

		public static float BallDrag(float radius)
		{
			float num = SilhouetteArea(radius);
			return 0.5f * BallFlightConstants.instance.dragCoeff * BallFlightConstants.instance.airDensity * num;
		}

		public static float BallLift(float radius)
		{
			float num = SilhouetteArea(radius);
			return 0.5f * BallFlightConstants.instance.liftCoeff * BallFlightConstants.instance.airDensity * num;
		}
	}

	private Vector3 lastTotalForce = Vector3.zero;

	private FlightParams currentBallData = default(FlightParams);

	public override void SetInitialConditions(FlightParams initialConditions, PhysicsBall ball)
	{
		base.initialConditions = initialConditions;
	}

	public override void Reset()
	{
		base.flightTime = 0f;
		lastTotalForce = Vector3.zero;
		currentBallData = base.initialConditions;
	}

	public override void Update(float deltaTime)
	{
		base.flightTime += deltaTime;
		UpdateBallParams(deltaTime);
	}

	private void UpdateBallParams(float deltaTime)
	{
		lastTotalForce = GetTotalForce(deltaTime);
		Vector3 vector = lastTotalForce / mass;
		currentBallData.position += currentBallData.velocity * deltaTime + 0.5f * vector * deltaTime * deltaTime;
		currentBallData.velocity += vector * deltaTime;
	}

	private Vector3 GetTotalForce(float deltaTime)
	{
		Vector3 vector = GravityForce();
		Vector3 vector2 = LiftForce(currentBallData.velocity);
		Vector3 vector3 = AirDragForce(currentBallData.velocity);
		Vector3 vector4 = vector + vector2 + vector3;
		Vector3 velocity = currentBallData.velocity + vector4 / mass * deltaTime;
		Vector3 vector5 = LiftForce(velocity);
		Vector3 vector6 = (vector2 + vector5) / 2f;
		Vector3 vector7 = AirDragForce(velocity);
		Vector3 vector8 = (vector3 + vector7) / 2f;
		return vector + vector6 + vector8;
	}

	private Vector3 GravityForce()
	{
		return Physics.gravity * mass;
	}

	private Vector3 LiftForce(Vector3 velocity)
	{
		Vector3 vector = PhysicsHelperFunctions.BallLift(radius) * Vector3Ex.LeftHandCross(currentBallData.angularVelocity * 2f * (float)Math.PI * radius, velocity);
		return vector.GetReverseHandedVector();
	}

	private Vector3 AirDragForce(Vector3 velocity)
	{
		return (0f - PhysicsHelperFunctions.BallDrag(radius)) * velocity.magnitude * velocity;
	}

	public override Vector3 Position()
	{
		return currentBallData.position;
	}

	public override Vector3 Velocity()
	{
		return currentBallData.velocity;
	}

	public override Vector3 AngularVelocity()
	{
		return currentBallData.angularVelocity;
	}

	public override FlightParams GetParamsAtHeight(float height)
	{
		if (lastTotalForce == Vector3.zero)
		{
			return default(FlightParams);
		}
		Vector3 vector = lastTotalForce / mass;
		float timeToRollBackToHeight = GetTimeToRollBackToHeight(height);
		FlightParams result = default(FlightParams);
		result.angularVelocity = currentBallData.angularVelocity;
		result.velocity = currentBallData.velocity - vector * timeToRollBackToHeight;
		result.position = currentBallData.position - currentBallData.velocity * timeToRollBackToHeight + 0.5f * vector * timeToRollBackToHeight * timeToRollBackToHeight;
		result.position.y = height;
		return result;
	}

	public override void RollBackToHeight(float height)
	{
		if (!(lastTotalForce == Vector3.zero))
		{
			Vector3 vector = lastTotalForce / mass;
			float timeToRollBackToHeight = GetTimeToRollBackToHeight(height);
			currentBallData.angularVelocity = currentBallData.angularVelocity;
			currentBallData.velocity -= vector * timeToRollBackToHeight;
			currentBallData.position -= currentBallData.velocity * timeToRollBackToHeight + 0.5f * vector * timeToRollBackToHeight * timeToRollBackToHeight;
			currentBallData.position.y = height;
			base.flightTime -= timeToRollBackToHeight;
		}
	}

	public override float GetTimeToRollBackToHeight(float height)
	{
		float num = height - currentBallData.position.y;
		float y = currentBallData.velocity.y;
		float num2 = lastTotalForce.y / mass;
		return (y + Mathf.Sqrt(y * y + 2f * num2 * num)) / num2;
	}
}
